package com.koron.standard.gradeStock.excel;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.util.ListUtils;
import com.koron.common.core.business.common.entity.TOrderNoMax;
import com.koron.common.core.business.common.service.TOrderNoMaxService;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.standard.gradeStock.bean.excel.GradeExcel;
import com.koron.standard.gradeStock.bean.po.Grade;
import com.koron.standard.gradeStock.bean.po.GradeItem;
import com.koron.standard.gradeStock.service.GradeItemService;
import com.koron.standard.gradeStock.service.GradeService;
import com.koron.standard.utils.StandardCodeTools;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author jzp
 * @since 2022/5/16
 */
@Slf4j
public class GradeExcelListener extends AnalysisEventListener<GradeExcel> {
    private static final int BATCH_COUNT = 100;

    private String prePatrolId;
    private Integer preRowIndex;

    /**
     * 缓存的数据
     */
    private final List<Grade> gradeList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    private List<GradeItem> gradeItemList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    private final GradeService gradeService;
    private final GradeItemService gradeItemService;
    private final TOrderNoMaxService tOrderNoMaxService;

    public GradeExcelListener(GradeService gradeService, GradeItemService gradeItemService, TOrderNoMaxService tOrderNoMaxService){
        this.gradeService = gradeService;
        this.gradeItemService = gradeItemService;
        this.tOrderNoMaxService = tOrderNoMaxService;
    }

    @Override
    public void invoke(GradeExcel data, AnalysisContext context) {
        Integer rowIndex = context.readRowHolder().getRowIndex();
        // 如果分类编码和名称不为空，则创建一条数据
        if (StrUtil.isNotEmpty(data.getTypeId()) && StrUtil.isNotEmpty(data.getName())) {
            Grade grade = data.buildGrade();
            gradeList.add(grade);
            prePatrolId = grade.getId();
            preRowIndex = rowIndex;
        }

        // 如果检查项名称不为空。则创建检查项
        if (StrUtil.isNotEmpty(data.getGradeName())) {
            GradeItem item = data.buildGradeItem(prePatrolId, rowIndex - preRowIndex);
            gradeItemList.add(item);
            // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
            if (gradeItemList.size() >= BATCH_COUNT) {
                saveGradeItem();
                // 存储完成清理 list
                gradeItemList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
            }
        }

    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        saveGrade();
        saveGradeItem();
        log.info("所有数据解析完成！");
    }

    private void saveGrade() {
        if (gradeList.size() == 0) {
            return;
        }
        // 设置code, appid, sort
        // 1.1 获取当天最大编码
        TOrderNoMax maxNo = tOrderNoMaxService.peekNoMax(StandardCodeTools.gradePrefix, null, gradeList.size());
        String prifix = StandardCodeTools.gradePrefix + maxNo.getDate();
        AtomicInteger atomicInteger = new AtomicInteger(maxNo.getMaxValue()-gradeList.size());
        // 1.2 获取水司id
        String appId = ThreadLocalContext.get().getAppId();

        for (Grade grade : gradeList) {
            grade.setCode(prifix + String.format("%0" + 3 + "d", atomicInteger.getAndIncrement()));
            grade.setAppid(appId);
        }
        log.info("{}条数据，开始存储数据库！", gradeList.size());
        gradeService.saveBatch(gradeList);
        log.info("存储数据库成功！");
    }

    private void saveGradeItem() {
        log.info("{}条数据，开始存储数据库！", gradeItemList.size());
        gradeItemService.saveBatch(gradeItemList);
        log.info("存储数据库成功！");
    }

}
